package com.ruoyi.laiwu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.laiwu.domain.bo.*;
import com.ruoyi.laiwu.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.laiwu.domain.vo.LwAlarmVo;
import com.ruoyi.laiwu.domain.LwAlarm;
import com.ruoyi.laiwu.mapper.LwAlarmMapper;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 告警Service业务层处理
 *
 * @author ruoyi
 * @date 2024-03-08
 */
@RequiredArgsConstructor
@Service
public class LwAlarmServiceImpl implements ILwAlarmService {

    private final LwAlarmMapper baseMapper;

    /**
     * 查询告警
     */
    @Override
    public LwAlarmVo queryById(Long id){


        return parse(baseMapper.selectVoById(id));
    }

    /**
     * 查询告警列表
     */
    @Override
    public TableDataInfo<LwAlarmVo> queryPageList(LwAlarmBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<LwAlarm> lqw = buildQueryWrapper(bo);
        Page<LwAlarmVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询告警列表
     */
    @Override
    public List<LwAlarmVo> queryList(LwAlarmBo bo) {
        LambdaQueryWrapper<LwAlarm> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<LwAlarm> buildQueryWrapper(LwAlarmBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<LwAlarm> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getSubId() != null, LwAlarm::getSubId, bo.getSubId());
        lqw.eq(StringUtils.isNotBlank(bo.getAlarmNo()), LwAlarm::getAlarmNo, bo.getAlarmNo());
        lqw.like(StringUtils.isNotBlank(bo.getAlarmSourceName()), LwAlarm::getAlarmSourceName, bo.getAlarmSourceName());
        lqw.eq(bo.getAlarmSourceType() != null, LwAlarm::getAlarmSourceType, bo.getAlarmSourceType());
        lqw.eq(StringUtils.isNotBlank(bo.getAlarmSourceCode()), LwAlarm::getAlarmSourceCode, bo.getAlarmSourceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getAlarmGrade()), LwAlarm::getAlarmGrade, bo.getAlarmGrade());
        lqw.eq(StringUtils.isNotBlank(bo.getAlarmType()), LwAlarm::getAlarmType, bo.getAlarmType());
        lqw.like(StringUtils.isNotBlank(bo.getAlarmTypeName()), LwAlarm::getAlarmTypeName, bo.getAlarmTypeName());
        lqw.eq(bo.getTimestamp() != null, LwAlarm::getTimestamp, bo.getTimestamp());
        lqw.eq(bo.getOrgId() != null, LwAlarm::getOrgId, bo.getOrgId());
        return lqw;
    }

    private final ILwAlarmFileService iLwAlarmFileService;

    private final ILwAlarmExtendService iLwAlarmExtendService;

    private final ILwAlarmDetailService iLwAlarmDetailService;

    private final ILwAlarmPositionService iLwAlarmPositionService;

    /**
     * 新增告警
     */
    @Override
    @Transactional
    public Boolean insertByBo(LwAlarmBo bo) {
        bo.setSubId(bo.getId());
        bo.setId(null);
        LwAlarm add = BeanUtil.toBean(bo, LwAlarm.class);
        validEntityBeforeSave(add);

        for (LwAlarmFileBo alarmFile : bo.getAlarmFiles()) {
            alarmFile.setSubId(bo.getSubId());
            iLwAlarmFileService.insertByBo(alarmFile);
        }
        LwAlarmExtendBo extend = bo.getExtend();
        extend.setSubId(bo.getSubId());
        iLwAlarmExtendService.insertByBo(extend);

        LwAlarmDetailBo alarmDetail = bo.getAlarmDetail();
        alarmDetail.setSubId(bo.getSubId());
        iLwAlarmDetailService.insertByBo(alarmDetail);

        LwAlarmPositionBo position = bo.getPosition();
        position.setSubId(bo.getSubId());
        iLwAlarmPositionService.insertByBo(position);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改告警
     */
    @Override
    public Boolean updateByBo(LwAlarmBo bo) {
        LwAlarm update = BeanUtil.toBean(bo, LwAlarm.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(LwAlarm entity){
        //TODO 做一些数据校验,如唯一约束
        LambdaQueryWrapper<LwAlarm> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LwAlarm::getSubId,entity.getSubId());
        Long l = baseMapper.selectCount(lqw);
        if(l>0){
            throw new GlobalException("同一条警报不能多次保存");
        }
    }

    /**
     * 批量删除告警
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<Map<String, Object>> listGroupByGrade() {

        return baseMapper.listGroupByGrade();
    }

    @Override
    public List<Map<String, Object>> listGroupBySourceType() {
        return baseMapper.listGroupBySourceType();
    }

    @Override
    public List<LwAlarmVo> listBySourceType(String sourceType) {
        LambdaQueryWrapper<LwAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LwAlarm::getAlarmSourceType,sourceType);
        wrapper.orderByDesc(LwAlarm::getTimestamp);
        List<LwAlarmVo> lwAlarmVos = baseMapper.selectVoList(wrapper);
        for (LwAlarmVo lwAlarmVo : lwAlarmVos) {
            parse(lwAlarmVo);
        }
        return lwAlarmVos;
    }

    @Override
    public List<LwAlarmVo> listByGrade(String grade) {
        LambdaQueryWrapper<LwAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LwAlarm::getAlarmGrade,grade);
        wrapper.orderByDesc(LwAlarm::getTimestamp);
        List<LwAlarmVo> lwAlarmVos = baseMapper.selectVoList(wrapper);
        for (LwAlarmVo lwAlarmVo : lwAlarmVos) {
            parse(lwAlarmVo);
        }
        return lwAlarmVos;
    }

    @Override
    public Long listAllCount() {
        LocalDate currentDate = LocalDate.now().minusDays(7L);
        LambdaQueryWrapper<LwAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(LwAlarm::getTimestamp,LocalDateTime.of(currentDate, LocalTime.MIN).toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
        return baseMapper.selectCount(wrapper);
    }

    public LwAlarmVo parse(LwAlarmVo lwAlarmVo){
        lwAlarmVo.setAlarmDetail(iLwAlarmDetailService.queryByAlarmId(lwAlarmVo.getSubId()));
        lwAlarmVo.setExtend(iLwAlarmExtendService.queryByAlarmId(lwAlarmVo.getSubId()));
        lwAlarmVo.setAlarmFiles(iLwAlarmFileService.queryByAlarmId(lwAlarmVo.getSubId()));
        lwAlarmVo.setPosition(iLwAlarmPositionService.queryByAlarmId(lwAlarmVo.getSubId()));

        return lwAlarmVo;
    }

    @Override
    public List<LwAlarmVo> queryInfo7_day() {
        LocalDate currentDate = LocalDate.now().minusDays(7L);
        LambdaQueryWrapper<LwAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(LwAlarm::getTimestamp,LocalDateTime.of(currentDate, LocalTime.MIN).toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
        wrapper.orderByDesc(LwAlarm::getTimestamp);
        List<LwAlarmVo> lwAlarmVos = baseMapper.selectVoList(wrapper);
        for (LwAlarmVo lwAlarmVo : lwAlarmVos) {
            parse(lwAlarmVo);
        }
        return lwAlarmVos;
    }

    @Override
    public List<Map<String, Object>> countBy_7_Day() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<LocalDateTime> days = get_7_day();
        ArrayList<Map<String, Object>> objects = new ArrayList<>();
        for (int i = 0; i < days.size()-1; i++) {
            HashMap<String, Object> result = new HashMap<>();
            LambdaQueryWrapper<LwAlarm> wrapper = new LambdaQueryWrapper<>();
            LocalDateTime localDateTime = days.get(i);
            LocalDateTime tom = days.get(i+1);
            wrapper.between(LwAlarm::getTimestamp,localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(),tom.toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
            // 使用格式化器对 LocalDateTime 进行格式化
            String formattedDateTime = localDateTime.format(formatter);
            result.put("date",formattedDateTime);
            result.put("num",baseMapper.selectCount(wrapper));
            objects.add(result);
        }

        return objects;
    }

    public static List<LocalDateTime>  get_7_day(){
        List<LocalDate> recentDates = new ArrayList<>();

        LocalDate currentDate = LocalDate.now().plusDays(1L);

        for (int i = 0; i < 8; i++) {
            LocalDate date = currentDate.minusDays(i);
            recentDates.add(date);
        }
        return recentDates.stream().map(i -> LocalDateTime.of(i, LocalTime.MIN)).collect(Collectors.collectingAndThen(Collectors.toList(), lst -> {
            Collections.reverse(lst);
            return lst;
        }));
    }

    public static void main(String[] args) {
        for (LocalDateTime localDateTime : get_7_day()) {
            System.out.println(localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
        }
        System.out.println(get_7_day());
    }
}
